package com.bright.hxj.cwduijie.service.impl;

import com.bright.ghj.common.config.BizThreadPoolExt;
import com.bright.ghj.common.util.DateUtil;
import com.bright.ghj.common.util.StringUtil;
import com.bright.hxj.cwduijie.manager.DataManager;
import com.bright.hxj.cwduijie.manager.DuijieManager;
import com.bright.hxj.cwduijie.pojo.command.ExecuteUpdateSqlCommand;
import com.bright.hxj.cwduijie.pojo.po.Contract;
import com.bright.hxj.cwduijie.service.GenerateShengNoService;
import com.bright.hxj.cwduijie.util.EntityManagerUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;

/**
 * @Author hxj
 * @Date 2024/11/28 10:04
 * @Description
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class GenerateShengNoServiceImpl implements GenerateShengNoService {

    private final EntityManager entityManager;
    private final BizThreadPoolExt bizPool;
    private final DuijieManager duijieManager;
    private final DataManager dataManager;


    @Override
    public void generateContractShengNo(List<Contract> contracts) {
        Map<String, Object> headMap = new ConcurrentHashMap<>();
        List<CompletableFuture<String>> futures = new ArrayList<>();
        for (Contract contract : contracts) {
            CompletableFuture<String> exceptionally = CompletableFuture.supplyAsync(() -> {
                        String cno = contract.getCODE();
                        Thread.currentThread().setName(cno + "_batch");

                        List<Map<String, Object>> maps1 = EntityManagerUtil.queryForMapList(entityManager, "select id as id,sheng_no as sheng_no from " + dataManager.getZcDBName() + "ht_contract where cno=:cno", Collections.singletonMap("cno", cno));
                        if (maps1.size() == 0) {
                            return null;
                        }
                        Object id = maps1.get(0).get("id");
                        String sheng_no = (String) maps1.get(0).get("sheng_no");
                        if (StringUtil.isNotBlank(sheng_no)) {
                            return sheng_no;
                        }

                        String head = contract.getTYSHXYDM() + "-" + (contract.getATTRIBUTE() == 10 ? "S" : "Z") + "-"
                                + DateUtil.getYearOrMonthOrDay(contract.getSIGNING_DATE(), Calendar.YEAR) + "-"; // 准备合同编号的头部

                        // 查看是否有同一个head的 有就获取同一个object进行加锁
//                        Object lockObject;
//                        if (headMap.containsKey(head)) {
//                            lockObject = headMap.get(head);
//                        } else {
//                            lockObject = new Object();
//                            headMap.put(head, lockObject);
//                        }
                        headMap.putIfAbsent(head, new Object());

                        String newNo;
                        synchronized (headMap.get(head)) {
                            System.out.println("进入synchronized " + cno + " head=" + head);
//                            try {
//                                Thread.sleep(2000);
//                            } catch (InterruptedException e) {
//                                throw new RuntimeException(e);
//                            }
                            // 到数据库查询这个head下最大的序列号
                            String querySQL = "select top 1 right(sheng_no,4) as no from " + dataManager.getZcDBName() + "ht_contract where sheng_no like :head order by sheng_no desc";
                            List<Map<String, Object>> maps = EntityManagerUtil.queryForMapList(entityManager, querySQL, Collections.singletonMap("head", head + "%"));

                            int newInt = 0;
                            if (maps.size() > 0 && maps.get(0).get("no") != null) {
                                // 最大序列号+1作为新序列号
                                newInt = Integer.parseInt(maps.get(0).get("no").toString());
                            }
                            newInt ++;
                            newNo = head + StringUtil.leftPad(String.valueOf(newInt), 4, "0");

                            // TODO 更新到中间表和基础表
                            Map<String, Object> params = new HashMap<>(2);
                            params.put("sheng_no", newNo);
                            params.put("id", id);
                            duijieManager.executeUpdateSql(new ExecuteUpdateSqlCommand("update " + dataManager.getZcDBName() + "ht_contract set sheng_no=:sheng_no where id=:id", params));
                        }

                        System.out.println(newNo);
                        return newNo;
                    }, bizPool)
                    .exceptionally(throwable -> {
                        throwable.printStackTrace();

                        return null;
                    });
            futures.add(exceptionally);

            
        }

        try {
            System.out.println("准备等待阻塞");
            CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
            voidCompletableFuture.get();

            System.out.println("222");
//            for (CompletableFuture<String> future : futures) {
//                System.out.println(future.get());
//            }
//            System.out.println("获得全部返回结果");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }
}
